package skyproc;

import java.io.IOException;
import java.util.Map;
import java.util.zip.DataFormatException;
import lev.LExportParser;
import lev.LFileChannel;
import lev.Ln;
import lev.LShrinkArray;
import skyproc.Mod.Mod_Flags;
import skyproc.exceptions.BadParameter;
import skyproc.exceptions.BadRecord;

/**
 *
 * @author Justin Swanson
 */
class SubStringPointer extends SubRecord {

    SubData data;
    SubString text;
    Files file;
    boolean forceExport = false;

    SubStringPointer(Type type, Files file) {
        super(type);
        data = new SubData(type, 0);
        text = new SubString(type, true);
        this.file = file;
    }

    @Override
    SubRecord getNew(Type type) {
        return new SubStringPointer(type, Files.STRINGS);
    }

    @Override
    public void clear() {
        text.clear();
        data.clear();
    }

    void setText(String textIn) {
        text.setString(textIn);
    }

    @Override
    Boolean isValid() {
        return text.isValid() && !text.print().equals("");
    }

    @Override
    void export(LExportParser out, Mod srcMod) throws IOException {
        if (isValid()) {
            if (srcMod.isFlag(Mod.Mod_Flags.STRING_TABLED)) {
                data.setData(Ln.toByteArray(srcMod.addOutString(text.string, file), 4));
                data.export(out, srcMod);
            } else {
                text.export(out, srcMod);
            }
        } else if (forceExport) {
            if (data.getData().length < 4) {
                data.setData(0, 4);
            }
            data.export(out, srcMod);
        }
    }

    @Override
    void parseData(LShrinkArray in) throws BadRecord, DataFormatException, BadParameter {
        data.parseData(in);
    }

    void fetchStringPointers(Mod srcMod, Record r, Map<Files, LFileChannel> streams) throws IOException {
        if (srcMod.isFlag(Mod_Flags.STRING_TABLED)) {
            if (data.isValid() && streams.containsKey(file)) {
                int index = Ln.arrayToInt(data.getData());
                if (srcMod.strings.get(file).containsKey(index)) {
                    int offset = srcMod.strings.get(file).get(index);
                    LFileChannel stream = streams.get(file);

                    stream.pos(offset);

                    switch (file) {
                        case STRINGS:
                            int input;
                            String string = "";
                            while ((input = stream.read()) != 0) {
                                string += (char) input;
                            }
                            text.setString(string);
                            break;
                        default:
                            int length = Ln.arrayToInt(stream.readInInts(0, 4));
                            String in = Ln.arrayToString(stream.readInInts(0, length - 1)); // -1 to exclude null end
                            if (!in.equals("")) {
                                text.setString(in);
                            }
                    }

                    if (logging() && SPGlobal.debugStringPairing) {
                        logSync("", r.toString() + " String pointer " + Ln.printHex(data.getData(), true, false) + " set to : " + print());
                    }

                } else {
                    if (logging() && SPGlobal.debugStringPairing) {
                        logSync("", r.toString() + " String pointer " + Ln.printHex(data.getData(), true, false) + " COULD NOT BE PAIRED");
                    }
                    data.setData(0); // Invalidate data to stop export
                }
            }
        } else {
            text.setString(Ln.arrayToString(data.getData()));
        }
    }

    @Override
    public String print() {
        if (text.isValid()) {
            return text.print();
        } else {
            return "<NO TEXT>";
        }
    }

    @Override
    int getContentLength(Mod srcMod) {
        if (isValid()) {
            if (srcMod.isFlag(Mod_Flags.STRING_TABLED)) {
                return 4; // length of 4
            } else {
                return text.getContentLength(srcMod);
            }
        } else {
            return 4; // empty data with 4 zeros
        }
    }

    @Override
    int getTotalLength(Mod srcMod) {
        if (isValid() || forceExport) {
            return getContentLength(srcMod) + getHeaderLength();
        } else {
            return 0;
        }
    }

    enum Files {

        STRINGS, ILSTRINGS, DLSTRINGS;
    }
}
